/*
 * @Author: Wangjun
 * @Date: 2021-05-15 22:43:19
 * @LastEditTime: 2023-04-07 15:53:27
 * @LastEditors: Wangjun
 * @Description:
 * @FilePath: \xrdatad:\go\src\gitee.com\haodreams\golib\exception\exception.go
 * hnxr
 */
package exception

import (
	"fmt"
	"runtime"
	"strings"

	"gitee.com/haodreams/golib/logs"
	"gitee.com/haodreams/libs/crash"
)

// Stack 堆栈信息
func Stack() []byte {
	buf := make([]byte, 1024)
	for {
		n := runtime.Stack(buf, false)
		if n < len(buf) {
			return buf[:n]
		}
		buf = make([]byte, 2*len(buf))
	}
}

// StackOK 。
func StackOK() string {
	stack := ""
	data := Stack()
	lines := strings.Split(string(data), "\n")
	for i := range lines {
		if i > 0 && i < 9 {
			continue
		}
		stack += lines[i] + "\n"
	}
	return stack
}

// GetInfo 获取系统信息
func GetInfo() (info string) {
	info = fmt.Sprintln("GO Version:", runtime.Version())
	info += fmt.Sprintln("ARCH:", runtime.GOARCH)
	info += fmt.Sprintln("OS:", runtime.GOOS)
	info += fmt.Sprintln("Number CPU:", runtime.NumCPU())
	info += fmt.Sprintln("Routine:", runtime.NumGoroutine())
	m := runtime.MemStats{}
	runtime.ReadMemStats(&m)
	if m.Alloc < 1024 {
		info += fmt.Sprintf("Malloc memory: %d bytes\n", m.Alloc)
	} else if m.Alloc < 1024*1024 {
		info += fmt.Sprintf("Malloc memory: %.3f K bytes\n", float64(m.Alloc)/1024)
	} else {
		info += fmt.Sprintf("Malloc memory: %.3f M bytes\n", float64(m.Alloc)/1024/1024)
	}
	info += "\n" + StackOK()
	return
}

// CatchException 捕获异常
func CatchException() {
	if err := recover(); err != nil {
		info := GetInfo()
		crash.WriteString(info)
		logs.Error("\nException:", err, "\n", info)
		//logs.GetBeeLogger().Flush()
	}
}

/**
 * @description: 支持异常捕获, paniced 是否继续抛出异常
 * @return {*}
 */
func Go(f func(), paniced ...bool) {
	go func() {
		defer func() {
			if err := recover(); err != nil {
				info := GetInfo()
				crash.WriteString(info)
				logs.Error("\nException:", err, "\n", info)
				if len(paniced) > 0 && paniced[0] {
					panic(err)
				}
			}
		}()
		f()
	}()
}
